spcas v0.01 documentation
Author: byuu
Release Date: 08/01/2004

Intro:
   spcas is a cross-assembler for the Sony SPC-700 processor, which is used in the SFC/SNES as a sound processor.

Features:
  • Supports all 256 opcodes
  • Supports labels and sublabels

    Brackets:
    Brackets, { and }, may be used anywhere within the code to help organize it structurally, they are converted to whitespace and then removed by the assembler.

    Labels and Sublabels:
    A label is used to represent a position in code, and allows one to code without having to constantly update branches and jumps/calls. A label can be used in most opcodes, on either side of the opcode, but I have only added explicit support for opcodes that might actually use this functionality. Those being: branches, jumps, calls. Labels can contain A-Za-z0-9_. They must end with : or ()
    A sublabel is used to declare labels within labels that will share its address space only, and can contain the same characters as a label, but must start with a period. A sublabel must not end with a : or (). Here's an example:

    proc1:
      nop
    .l1
      bra .l1
    proc2:
      nop
    .l1
      bra .l1

    Sublabels allow you to reuse redundantly named labels such as loop, end, etc. without causing duplicate label conflicts. A new sublabel group is started immediately after a label is declared automatically.

    : Separator
    The : is used to allow multiple opcodes on the same line. It requires a space before and after usage, to differentiate it from the : used to end labels.
    Example: mov a,$00 : nop
    This is useful for making each line define an action, rather than just an opcode. Very useful when combined with { } to indicate a structural flow of assembly code, rather than a straight descending list. But you're free to code however you like.

    Math:
    Math is supported in all opcodes, and all functions, however, it has one major variation from traditional math. It does not resolve math in order if symbols, it instead resolves from left to right, and also does not use parinthesis to denote order. An example:
    Standard Math:
       mov a,5+6*2 ;=17
    Left-to-right Math:
       mov a,6*2+5 ;=17
       mov a,5+6*2 ;=22
    I do apologize for this limitation, it was just far easier and faster to implement left-to-right math, and for an assembler, I haven't really come across anything that could not be represented in left-to-right math. To use left-to-right math, just reorder your multiplication and division to the start, and use addition and subtraction at the end. The math system supports the following commands:
    + : Addition
    - : Subtraction
    * : Multiplication
    / : Division
    << : Left-shift ( x< >> : Right-shift ( x >> y formula: x = x / 2^y )
    & : Bitwise AND
    | : Bitwise OR
    ^ : Bitwise XOR (Note: Not exponentials)
    ~ : Bitwise NOT


    Math also works with labels. Example:
    mov a,label2-label1+2

    Additional Commands:

    incbin:
    The incbin command will let you insert a binary file into the output binary image. Usage:
    incbin filename.bin

    fill / fillbyte:
    fillbyte will allow you to select the byte used by fill, and fill can be used to fill x number of bytes with the fillbyte. Example:
    fillbyte $ff : fill 16
    This will write 16 $ff's to the file, and will increment the pc counter automatically.

    pad / padbyte:
    This is identical to fill / fillbyte, except that pad takes an offset instead of a number of bytes to write. It will continue writing bytes until the offset is reached. Example:
    org $0200 : padbyte $ff : pad $0210
    This will write 16 $ff's to the file, and will increment the pc counter automatically.

    db / dw / dl / dd:
    These are used to write binary data to the file.
  • db - 8-bit byte write mode
  • dw - 16-bit word write mode
  • dl - 24-bit long write mode
  • dd - 32-bit dword write mode
    Multiple arguments can be passed to these commands by means of a comma. Example:
    db $01,$02,$03,$04
    dw $0001,$0002,$0003,$0004
    This command also accepts labels and text as arguments, example:
    dw label : db "This is a test",$00
    Text is written using the ascii table. There is no table support, as this is, after all, a sound processor.

    org:
    org is used to set the file position. It will not update the base location, you must set the base location manually after using org! If you seek to a position past the current position in the file, the null space will be filled with 00's. You are free to seek backwards into an existing file, if need be.

    loadpc / savepc / warnpc: These are used for spanning multiple files, and warning when you exceed certain ranges. loadpc will load in a file, which is an index of pc addresses. You can specify just loadpc filename.xpc, or you can specify an index into this file, such as loadpc filename.xpc,2. If no index is specified, 0 is assumed. It will seek to index * 2, and read in two bytes, then set pc to this value. savepc works the same way, except it will save the pc value to specified index location. You can use these two in conjunction to assemble multiple files without having to space the code apart due to fears of the first files code size growing too large and cutting into the second files code, then the second file eating the first files code. warnpc just takes an address, it will compare the current pc to the address you specified, if the current address is >= the address specified, it will give you an error. Useful if you want your code to be between x and y, and data to be between y and z. You can make sure your code isn't so large that it exceeds y this way.

    base:
    base is used to set the pc position, which is used to calculate label positions. You could be at file offset 0, and set the base to $200, then, even though you are assembling to $0 in the binary file, it will be treated as though you were assembling to $200 in regards to branch/jump/call instructions. This is useful for spc-700 assembly, as the file location is generally not where you load the code into its RAM at.

    Additional Notes:
    As I have just begun learning spc700 assembly, I am not too sure what commands would be useful for this processor, and I believe the org/base solution I used presently will quickly prove inferior. I do plan on improving this in due time, as I get used to programming for the system. So expect that to change in future releases... I hope to add defines, and +/- labels to this assembler in the future, as well. But I don't plan on adding incsrc or macros, as spc700 assembly routines for entire games are usually under 4kbytes in binary form. Time will tell, however...

    Opcodes:
    Please see the included test.asm file for a list of opcodes. I also plan to add useful psuedo-opcodes in the future.